﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;
using System.Management.Automation.Provider;
using System.ComponentModel;
using PowerOBIProvider.OBI;
using PowerOBIPRovider.OBIWebReference;
using System.Collections.ObjectModel;
using System.Security.AccessControl;
using System.Collections;
using PowerOBIProvider;
using PowerOBIProvider.Cmdlts;
namespace PowerOBIProvider
{
    [CmdletProvider("PowerOBIProvider",ProviderCapabilities.ShouldProcess)]
    public class PowerOBIProvider : NavigationCmdletProvider, 
        ISecurityDescriptorCmdletProvider
    {
        public PSOBIDriveInfo obiDriveInfo = null;
        protected override PSDriveInfo NewDrive(PSDriveInfo drive)
        {
            
            RuntimeDefinedParameterDictionary dynamicParameters = base.DynamicParameters as RuntimeDefinedParameterDictionary;
            string server = dynamicParameters["server"].Value.ToString();
            string username = dynamicParameters["username"].Value.ToString();
            string password = dynamicParameters["password"].Value.ToString();
            obiDriveInfo= new PSOBIDriveInfo(drive, server,username, password);
            return obiDriveInfo;
        }

        protected override PSDriveInfo RemoveDrive(PSDriveInfo drive)
        {
            PSOBIDriveInfo obiDriveInfo = drive as PSOBIDriveInfo;

            if (obiDriveInfo != null)
            {
                obiDriveInfo.ObiWSClient.Disconnect();
            }

            return obiDriveInfo;
        }

        protected override bool IsValidPath(string path)
        {
            PSOBIDriveInfo obiDriverInfo = base.PSDriveInfo as PSOBIDriveInfo;
            try
            {

                if ( obiDriverInfo.ObiWSClient.GetItemInfo(path) != null )
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                return false;
            }

        }

        protected override bool ItemExists(string path)
        {
               return IsValidPath(path);
        }

        protected override bool IsItemContainer(string path)
        {
            PSOBIDriveInfo obiDriveInfo = base.PSDriveInfo as PSOBIDriveInfo;
            return obiDriveInfo.ObiWSClient.IsCatalog(path);
        }
        protected override void GetItem(string path)
        {
            PSOBIDriveInfo obiDriveInfo = base.PSDriveInfo as PSOBIDriveInfo;

            WriteItemObject(obiDriveInfo.ObiWSClient.ReadItem(path), path, obiDriveInfo.ObiWSClient.IsCatalog(path));
            
        }
        protected override void GetChildItems(string path, bool recurse)
        {
            PSOBIDriveInfo obiDriverInfo = base.PSDriveInfo as PSOBIDriveInfo;
            ItemInfo[] subItems = obiDriverInfo.ObiWSClient.GetChildItems(path,"*");
            if ( !recurse )
            {
                foreach ( ItemInfo item in subItems )
                {
                    WriteItemObject(item, item.path, obiDriverInfo.ObiWSClient.IsCatalogFromItemInfo(item));
                }
            }
            else
            {
                foreach ( ItemInfo item in subItems )
                {
                    if ( item.type == ItemInfoType.Folder )
                    {
                        GetChildItems(item.path, true);
                    }
                    else
                        WriteItemObject(item, item.path, obiDriverInfo.ObiWSClient.IsCatalogFromItemInfo(item));

                }
            }
        }
        protected override object CopyItemDynamicParameters(string path, string destination, bool recurse)
        {
            return base.CopyItemDynamicParameters(path, destination, recurse);
        }
        protected override bool HasChildItems(string path)
        {
            PSOBIDriveInfo obiDriverInfo = base.PSDriveInfo as PSOBIDriveInfo;
            ItemInfo[] subItems = obiDriverInfo.ObiWSClient.GetChildItems(path,"*");
            if (subItems != null  && subItems.Length > 0)
                return true;
            else
                return false;
        }
        protected override string GetChildName(string path)
        {
                return base.GetChildName(path);
        }
        protected override void GetChildNames(string path, ReturnContainers returnContainers)
        {
            PSOBIDriveInfo obiDriverInfo = base.PSDriveInfo as PSOBIDriveInfo;
            ItemInfo[] subItems = obiDriverInfo.ObiWSClient.GetChildItems(path,"*");
            foreach (ItemInfo item in subItems)
            {
                WriteItemObject(item.caption, item.path, obiDriverInfo.ObiWSClient.IsCatalogFromItemInfo(item));
            }
        }
        protected override object GetChildNamesDynamicParameters(string path)
        {
            return base.GetChildNamesDynamicParameters(path);
        }

        protected override string GetParentPath(string path, string root)
        {
            //return base.GetParentPath(path, root);
            //rewrite this with better approach
            string pathClear = path.Replace("\\/","##!##");
            int lastDelimiterIndex = pathClear.LastIndexOf('/');
            if (lastDelimiterIndex == -1)
                return "/";
            else
            {
                string parentPath = pathClear.Substring(0, lastDelimiterIndex);
                parentPath = parentPath.Replace("##!##", "\\/");
                //if (parentPath == "")
                //    return "";
                //else
                return parentPath;
            }
        }

        protected override string NormalizeRelativePath(string path, string basePath)
        {
            //string normalizedPath = base.NormalizeRelativePath(path, basePath);
            string normalizedPath = path;
            normalizedPath = normalizedPath.TrimStart('\\');
            normalizedPath = "/" + normalizedPath;
            return normalizedPath;
            
        }

        protected override string MakePath(string parent, string child)
        {
            //return base.MakePath(parent, child);
            string path = parent + "/" + child;
            path = path.TrimStart('/');
            path = "/" + path;
            return path;
        }

        //ACL 
        public void GetSecurityDescriptor(string path, AccessControlSections includeSections)
        {
            PSOBIDriveInfo obiDriverInfo = base.PSDriveInfo as PSOBIDriveInfo;
            ArrayList permissions = obiDriverInfo.ObiWSClient.GetPermissionForItem(path);
            bool isContainer = obiDriverInfo.ObiWSClient.IsCatalog(path);
            foreach (Permission permission in permissions)
            {
                WriteItemObject(permission, path, isContainer);
            }
            
        }
        public ObjectSecurity NewSecurityDescriptorFromPath(string path, AccessControlSections includeSections)
        {
            FileSecurity fs = new FileSecurity();
            return fs;
        }
        public ObjectSecurity NewSecurityDescriptorOfType(string type, AccessControlSections includeSections)
        {
            FileSecurity fs = new FileSecurity();
            return fs;
        }

        public void SetSecurityDescriptor(string path, ObjectSecurity securityDescriptor)
        {


        }


        //remove-item
        protected override void RemoveItem(string path, bool recurse)
        {
            if(IsValidPath(path) )
            {
                if ( this.ShouldProcess(path, "remove a WebCatalog object") )
                {
                    PSOBIDriveInfo obiDriverInfo = base.PSDriveInfo as PSOBIDriveInfo;
                    obiDriverInfo.ObiWSClient.RemoveItem(path, recurse);
                }
            }
        }
        protected override object RemoveItemDynamicParameters(string path, bool recurse)
        {
            return base.RemoveItemDynamicParameters(path, recurse);
            
            
        }

        
        //new-item
        protected override void NewItem(string path, string itemTypeName, object newItemValue)
        {
            try
            {
                PSOBIDriveInfo obiDriveInfo = base.PSDriveInfo as PSOBIDriveInfo;
                obiDriveInfo.ObiWSClient.CreateFolder(path);
            }
            catch (Exception ex)
            {
                WriteError(new ErrorRecord(ex, "0", ErrorCategory.OperationStopped, null));
            }
        }
        //move-item
        protected override void MoveItem(string path, string destination)
        {
            try
            {
                CopyItem(path, destination, false);
                obiDriveInfo.ObiWSClient.RemoveItem(path, true);
            }
            catch (Exception ex)
            {
                WriteError(new ErrorRecord(ex, "0", ErrorCategory.OperationStopped, null));
            }
        }

        //copy-item
        protected override void CopyItem(string path, string copyPath, bool recurse)
        {
            try
            {

                PSOBIDriveInfo obiDriveInfo = base.PSDriveInfo as PSOBIDriveInfo;

                CatalogObject catObject = obiDriveInfo.ObiWSClient.ReadItem(path);
                if (catObject.itemInfo.type == ItemInfoType.Folder || catObject.itemInfo.type == ItemInfoType.Link)
                    throw new Exception("Only objects can be moved/copied - folders or links are currently not supported");
                else if (catObject.itemInfo.type == ItemInfoType.NoAccess)
                    throw new Exception("You do not have sufficient right to read this object");
                else if (catObject.itemInfo.type == ItemInfoType.Missing)
                    throw new Exception("Object does not exist.");
                string normalizedDestination = copyPath.Replace(catObject.itemInfo.caption, "").TrimEnd('/') + '/' + catObject.itemInfo.caption;
                obiDriveInfo.ObiWSClient.WriteItem(catObject, normalizedDestination);
                obiDriveInfo.ObiWSClient.UpdateItemACL(catObject.itemInfo.acl, normalizedDestination, false);
            }
            catch (Exception ex)
            {
                WriteError(new ErrorRecord(ex, "0", ErrorCategory.OperationStopped, null));
            }
        }
        protected override object NewDriveDynamicParameters()
        {
            //WriteVerbose("PowerOBIProvider::NewDriveDynamicParameters()");

            RuntimeDefinedParameterDictionary dynamicParameters = new RuntimeDefinedParameterDictionary();
            Collection<Attribute> atts = new Collection<Attribute>();
            ParameterAttribute parameterAttribute = new ParameterAttribute();
            parameterAttribute.Mandatory = true;
            atts.Add(parameterAttribute);
            dynamicParameters.Add("server", new RuntimeDefinedParameter("server", typeof(string), atts));
            dynamicParameters.Add("username", new RuntimeDefinedParameter("username", typeof(string), atts));
            dynamicParameters.Add("password", new RuntimeDefinedParameter("password", typeof(string), atts));

            return dynamicParameters;
        }

        

    }

    
    
}